


#include "frameanimation.h"
#include "gamemanager.h"
#include "resourcemanager.h"

FrameAnimation::FrameAnimation(void): _frameRate(0), _frameIndex(0), _isLoop(true), _paused(false), _finished(false), _needRemoveAfterFinished(false), _frameCount(0),_elapsedTime(0), _frameRateFactor(1) {
}

FrameAnimation::~FrameAnimation(void){
}

void FrameAnimation::set(const AnimationInfo& info) {
	CCAssert(info.key != "", "animation key is empty.");

	_animKey = info.key;
	_frames.clear();
	_frames.insert(_frames.begin(), info.frames.begin(), info.frames.end());

	setFrame(0);

	_frameCount = info.frames.size();
	_frameRate = info.frameRate;

	_frameIndex = 0;
	_finished = false;
	_isLoop = true;
	_paused = false;

	_elapsedTime = 0;
	_frameRateFactor = 1;

	_needRemoveAfterFinished = false;
}

void FrameAnimation::setFrame(int index){
	if(!_frames.empty() && index >= 0 && index < (int)_frames.size()) {
		setDisplayFrame(MAKE_SPRITEFRAME(_frames[index].c_str()));
		if(_frameIndex != index) {
			_frameIndex = index;
		}
	}
}

void FrameAnimation::setLogicPosition(const CCPoint& pos) {
    _logicPosition = pos;
    setPosition(SCALE_PT(pos));
}

void FrameAnimation::update(float ticks) {
	if (_paused || _frameCount == 1 || _finished)
		return;

	float num = _frameRate * _frameRateFactor;

	_elapsedTime += ticks;
	if (_elapsedTime < num)
		return;

	int n = static_cast<int>(_elapsedTime / num);
	_elapsedTime -= num * n;
	_frameIndex += n;

	if (_frameIndex >= _frameCount) {
		if (!_isLoop) {
			_finished = true;
		} else {
			_frameIndex = 0;
		}
	}

	setFrame(_frameIndex);
}

AnimationSequence::AnimationSequence(int id) : _id(id), _playingAnimIndex(0), _timeElapsed(0), _parent(nullptr) {
}

AnimationSequence::~AnimationSequence() {
	for(size_t i = 0; i < _arrAnims.size(); i++) {
		FrameAnimation * anim = _arrAnims[i];
		if(anim) {
			if(static_cast<int>(i) == _playingAnimIndex) {
				_parent->removeChild(anim, true);
			}

			if(anim) {
				anim->release();
			};
			_arrAnims[i] = nullptr;
		}
	}

	_arrAnims.clear();
}

bool AnimationSequence::isFinished() {
	return _playingAnimIndex >= (int)_arrAnims.size();
}

void AnimationSequence::playFirst() {
	if(!_arrAnims.empty()) {
		_playingAnimIndex = 0;
		FrameAnimation * anim = _arrAnims[_playingAnimIndex];

		int zorder = 0;

		_parent->addChild(_arrAnims[_playingAnimIndex], zorder, anim->getTag());
	} else {

	}
}

void AnimationSequence::playNext() {
	_playingAnimIndex++;

	if(_playingAnimIndex < (int)_arrAnims.size()) {
		FrameAnimation * anim = _arrAnims[_playingAnimIndex];

		int zorder = 0;

		_parent->addChild(anim, zorder, anim->getTag());
	} else {

	}

	_timeElapsed = 0;
}

void AnimationSequence::update(float ticks) {
	if(_playingAnimIndex < (int)_arrAnims.size()) {
		FrameAnimation * anim = _arrAnims[_playingAnimIndex];
		if(anim) {
			if(anim->isFinished() || _timeElapsed > _arrDurationss[_playingAnimIndex]) {
				_parent->removeChild(anim, true);
				if(anim) {
					anim->release();
				};

				_arrAnims[_playingAnimIndex] = nullptr;

				playNext();
			} else {
				anim->update(ticks);

				if(_arrLoops[_playingAnimIndex]) {
					_timeElapsed += ticks;
				}
			}
		}
	}
}

void AnimationSequence::add(FrameAnimation * anim, bool needLoop, float duration) {
	anim->setLoop(needLoop);

	_arrAnims.push_back(anim);
	_arrLoops.push_back(needLoop);
	_arrDurationss.push_back(duration);
}
